#include "event_loop.hpp"
#include <unistd.h>
#include <cstring>
#include <stdexcept>

// 构造函数：创建 epoll 实例并预分配事件数组
EventLoop::EventLoop(size_t max_events = 64)
    : max_events_(max_events),
      events_(std::make_unique<struct epoll_event[]>(max_events_)),
      epoll_fd_(epoll_create1(0))
{
    if (epoll_fd_ == -1)
    {
        throw std::runtime_error("epoll_create1 failed: " + std::string(strerror(errno)));
    }
}

// 析构函数
// 确保关闭 epoll 文件描述符
EventLoop::~EventLoop()
{
    if (epoll_fd_ != -1)
    {
        close(epoll_fd_);
    }
}

// 添加事件到事件循环
// @param fd: 文件描述符
// @param events: 要监听的事件类型
// @param callback: 事件发生时的回调函数
void EventLoop::add(int fd, uint32_t events, EventCallback callback)
{
    std::lock_guard<std::mutex> lock(mutex_); // 加锁保护并发访问

    struct epoll_event ev;
    ev.events = events;
    ev.data.fd = fd;

    if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &ev) == -1)
    {
        throw std::runtime_error("Failed to add event to epoll: " + std::string(strerror(errno)));
    }

    callbacks_[fd] = std::move(callback); // 存储回调函数
}

// 修改已存在的事件配置
// @param fd: 要修改的文件描述符
// @param events: 新的事件类型
void EventLoop::modify(int fd, uint32_t events)
{
    std::lock_guard<std::mutex> lock(mutex_);

    struct epoll_event ev;
    ev.events = events;
    ev.data.fd = fd;

    if (epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &ev) == -1)
    {
        throw std::runtime_error("Failed to modify event in epoll" + std::string(strerror(errno)));
    }
}

// 从事件循环中移除事件
// @param fd: 要移除的文件描述符
void EventLoop::remove(int fd)
{
    std::lock_guard<std::mutex> lock(mutex_);

    if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, nullptr) == -1)
    {
        throw std::runtime_error("Failed to remove event from epoll" + std::string(strerror(errno)));
    }

    callbacks_.erase(fd); // 移除对应的回调函数
}

// 运行事件循环
// 持续监听和处理事件，直到 stop() 被调用
void EventLoop::run()
{
    std::lock_guard<std::mutex> lock(running_mutex_);
    running_ = true;

    while (running_)
    {
        // 等待事件发生，-1 表示无限等待
        int nfds = epoll_wait(epoll_fd_, events_.get(), max_events_, -1);
        if (nfds == -1)
        {
            if (errno == EINTR)
            { // 被信号中断，继续等待
                continue;
            }
            throw std::runtime_error("epoll_wait failed" + std::string(strerror(errno)));
        }

        // 处理所有就绪的事件
        processEvents(nfds);
    }
}

void EventLoop::processEvents(int nfds)
{
    for (int i = 0; i < nfds; ++i)
    {
        int fd = events_[i].data.fd;
        uint32_t revents = events_[i].events;

        std::lock_guard<std::mutex> lock(mutex_);
        auto it = callbacks_.find(fd);
        if (it != callbacks_.end())
        {
            it->second(revents); // 调用对应的回调函数
        }
    }
}

// 停止事件循环
void EventLoop::stop()
{
    running_ = false;
}